﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using DbGenerator.Model.units.constraint.root;
using DbGenerator.Model.units.constraint.types;
using Unity.Errors.types;
using DbGenerator.Model.units.table;
using DbGenerator.Model.attributes.types;
using DbGenerator.Model.units.column.relations;
using DbGenerator.Utilities;

namespace DbGenerator.Model.units.column
{
    public class TColumn : IEquatable<TColumn>
    {
        #region ctors
        public TColumn(TColumnAttribute columnAttribute)
        {
            _ColumnIdentity = Guid.NewGuid();
            _ColumnInfo = columnAttribute;
            _AutoIncrementInfo = new TAutoIncrementInfo();
            _ColumnAlias = new TAlias(columnAttribute.ColumnName);
        }
        #endregion

        #region public methods
        public void ConnectTo(TTable referencedTable)
        {
            _Connector = new TFKConnector(this);
            _Connector.ConnectTo(referencedTable);
        }
        public void SetBaseTable(TTable tBase)
        {
            _BaseTable = tBase;
        }
        public void SetPKConstraint(TPKConstraint pkConstraint)
        {
            _PKConstraint = pkConstraint;
        }
        public void SetUQConstraint(TUQConstraint uqConstraint)
        {
            _UQConstraint = uqConstraint;
        }
        public void SetFKConstraint(TFKConstraint fkConstraint)
        {
            _FKConstraint = fkConstraint;
        }
        public void SetDKConstraint(TDKConstraint dkConstraint)
        {
            _DKConstraint = dkConstraint;
        }
        public void SetCKConstraint(TCKConstraint ckConstraint)
        {
            _CKConstraint = ckConstraint;
        }
        #endregion

        #region Constraint Sets
        private TPKConstraint _PKConstraint;
        public TPKConstraint PKConstraint
        {
            get { return _PKConstraint; }
            protected set { _PKConstraint = value; }
        }

        private TCKConstraint _CKConstraint;
        public TCKConstraint CKConstraint
        {
            get { return _CKConstraint; }
            protected set { _CKConstraint = value; }
        }

        private TDKConstraint _DKConstraint;
        public TDKConstraint DKConstraint
        {
            get { return _DKConstraint; }
            protected set { _DKConstraint = value; }
        }

        private TUQConstraint _UQConstraint;
        public TUQConstraint UQConstraint
        {
            get { return _UQConstraint; }
            protected set { _UQConstraint = value; }
        }

        private TFKConstraint _FKConstraint;
        public TFKConstraint FKConstraint
        {
            get { return _FKConstraint; }
            protected set { _FKConstraint = value; }
        }
        #endregion

        #region private methods
        private void SignAsAutoIncrementColumn(bool sign)
        {
            if (sign)
            {
                SErrorManager.CustomError()
                    .Assert(SDbTypeUtilities.IsNumeric(_ColumnInfo.DataType)
                     , new TErrorInfo(GetType(), "SignAsAutoIncrementColumn")
                     , "Column {0} is not numeric. Impossible to sign as auto incremented column"
                     , _ColumnInfo.ColumnName);
                _ColumnInfo.AutoIncrement = true;
            }
            else
                _ColumnInfo.AutoIncrement = false;
        }
        #endregion

        #region overriden methods
        public override string ToString()
        {
            //[ID] [int] IDENTITY(1,1) NOT NULL,
            //[Kod] [nvarchar](50) NULL,
            string identity =
                (_ColumnInfo.AutoIncrement)
                    ? _AutoIncrementInfo.ToString()
                    : "";
            string nullable = (_ColumnInfo.AllowNulls)
                ? "NULL" : "NOT NULL";
            string maxLength = "";
            if (SDbTypeUtilities.IsNumeric(_ColumnInfo.DataType))
                maxLength = "";
            else if (SDbTypeUtilities.IsText(_ColumnInfo.DataType))
            {
                if (_ColumnInfo.MaxLength == Int32.MinValue
                    || _ColumnInfo.MaxLength == -1)
                    maxLength = "(MAX)";
                else
                    maxLength = "(" + _ColumnInfo.MaxLength + ")";
            }
            return String.Format("[{0}] [{1}]{2} {3} {4}"
                , _ColumnInfo.ColumnName
                , SDbTypeUtilities.GetColumnType(_ColumnInfo.DataType)
                , maxLength
                , identity
                , nullable); ;
        }
        #endregion

        #region properties
#warning insert table reference and db info here
        private Guid _ColumnIdentity;
        public Guid ColumnIdentity
        {
            get { return _ColumnIdentity; }
        }
        private TFKConnector _Connector;
        public TFKConnector Connector
        {
            get { return _Connector; }
        }
        private TTable _BaseTable;
        public TTable BaseTable
        {
            get { return _BaseTable; }
            set { _BaseTable = value; }
        }

        private TAutoIncrementInfo _AutoIncrementInfo;
        public TAutoIncrementInfo AutoIncrementInfo
        {
            get
            {
                if (_ColumnInfo.AutoIncrement)
                    return _AutoIncrementInfo;
                SErrorManager.Exception()
                    .Throw(new NotImplementedException()
                    , new TErrorInfo(GetType(), "AutoIncrementInfo.get")
                    , "IsAutoIncrement must be set to true to get this property");
                return null;
            }
            //set { _AutoIncrementInfo = value; }
        }

        private TColumnAttribute _ColumnInfo;
        public TColumnAttribute ColumnInfo
        {
            get { return _ColumnInfo; }
        }

        private object _DataValue;
        public object DataValue
        {
            get { return _DataValue; }
            set { _DataValue = value; }
        }

        private TAlias _ColumnAlias;
        public TAlias ColumnAlias
        {
            get { return _ColumnAlias; }
            set { _ColumnAlias = value; }
        }
        #endregion

        #region IEquatable<TColumn> Members

        public bool Equals(TColumn other)
        {
            return this.ColumnIdentity.Equals(other.ColumnIdentity);
        }

        #endregion
    }
}
